﻿using ExcelUnity.Core;
using ExcelUnity.Importer.Importers;
using ExcelUnity.Importer.Wrappers.SheetDataBuilders;
using NPOI.SS.UserModel;
using System.Collections.Generic;
using System.Linq;

namespace ExcelUnity.Importer.Wrappers.SheetWraperBuilders
{
    public class ExcelSheetWrapperBuilder
    {
        public static List<SheetWrapper> BuildSheetWrappersByExcel(ImportBook importBook, IWorkbook workBook)
        {
            var sheetWrappers = new List<SheetWrapper>();
            foreach (var importSheet in importBook.Sheets)
            {
                ISheet? sheet;
                if (importSheet.SheetMatchType == SheetMatchType.SheetIndex)
                    sheet = workBook.GetSheetOrNull(importSheet.SheetIndex);
                else
                    sheet = workBook.GetSheetOrNull(importSheet.SheetName!);
                if (sheet == null)
                    continue;

                var (columnWrappers, columnError) = BuildColumnWrappers(sheet, importSheet);
                if (columnError.IsNotNullOrWhiteSpace())
                {
                    sheetWrappers.Add(new SheetWrapper(importSheet, workBook.GetSheetIndex(sheet), sheet.SheetName) { SheetError = columnError });
                    continue;
                }

                var sheetWrapper = BuildSheetWrapper(sheet, workBook.GetSheetIndex(sheet), importSheet, columnWrappers!);

                sheetWrapper.ModelData = SheetDataModelBuilder.BuildSheetDataModel(sheetWrapper, importSheet.DataType);

                sheetWrapper.Validate();
                sheetWrappers.Add(sheetWrapper);
            }

            return sheetWrappers;
        }

        private static (List<ColumnWrapper>? ColumnWrappers, string? ErrorMessage) BuildColumnWrappers(ISheet sheet, ImportBookSheet importSheet)
        {
            if (sheet.LastRowNum == 0) return (null, "表格没有数据");

            IRow? columnRow = null;
            if (importSheet.HeaderRowIndex.HasValue)
            {
                if (sheet.LastRowNum >= importSheet.HeaderRowIndex)
                    columnRow = sheet.GetRow(importSheet.HeaderRowIndex.Value);
                else
                    return (null, "未找到表头行");
            }
            else
            {
                columnRow = sheet.GetRow(sheet.FirstRowNum); ;
            }

            if (columnRow.IsEmptyOrNull())
                return (new List<ColumnWrapper>(), importSheet.HeaderRowIndex == null ? "表格没有数据" : "未找到表头行");

            var columnWrappers = Enumerable.Range(columnRow!.FirstCellNum, columnRow.LastCellNum - columnRow.FirstCellNum)
                                           .Select(x => new ColumnWrapper(x, importSheet.HeaderRowIndex.HasValue ? columnRow.GetCell(x).GetValue() : null))
                                           .ToList();

            if (columnWrappers.IsNullOrEmpty())
                return (columnWrappers, importSheet.HeaderRowIndex == null ? "表格没有数据" : "未找到表头行");

            var bindError = ColumnWrapperBinder.BindColumWrapperToDataType(columnWrappers, importSheet.DataType, importSheet.ColumnMatchType);
            return (columnWrappers, bindError);
        }



        private static SheetWrapper BuildSheetWrapper(ISheet sheet, int sheetIndex, ImportBookSheet importSheet, List<ColumnWrapper> columnWrappers)
        {
            var sheetWrapper = new SheetWrapper(importSheet, sheetIndex, sheet.SheetName)
            {
                Columns = columnWrappers,
                DataRowStartIndex = importSheet.HeaderRowIndex.HasValue ? importSheet.HeaderRowIndex.Value + 1 : sheet.FirstRowNum,
                Rows = new List<RowWrapper>()
            };

            var minColumnIndex = sheetWrapper.Columns.Min(x => x.ColumnIndex);
            var maxColumnIndex = sheetWrapper.Columns.Max(x => x.ColumnIndex);
            for (int rowIndex = sheetWrapper.DataRowStartIndex.Value; rowIndex <= sheet.LastRowNum; rowIndex++)
            {
                var row = sheet.GetRow(rowIndex);
                if (row.IsEmptyOrNull(minColumnIndex, maxColumnIndex))
                    continue;

                var cellWrappers = sheetWrapper.Columns.Select(x => new CellWrapper(x.ColumnIndex, row.GetCell(x.ColumnIndex).GetValue(), x.IsUnique, x.PropertyName)).ToList();
                sheetWrapper.Rows.Add(new RowWrapper(rowIndex, cellWrappers));
            }

            return sheetWrapper;
        }
    }
}
